/*
 *  $Id: Graveyard.cs 1233 2010-12-18 17:54:48Z thenn.erannor $
 *  This file is a part of Ragima CCG.
 *  (C) 2008-2010 Ragima development group.
 *
 *  Licensed under the terms of the GNU GPL License version 2.
 *
 */

using System;
using System.Collections.Generic;

using AgateLib;
using AgateLib.Geometry;

using Nereal.Extensions;
using Nereal.Serialization;

namespace Ragima {
    /// <summary>
    /// Тип цели: карта в могильнике.
    /// </summary>
    public class GraveyardTarget : TargetType {
        /// <summary>
        /// Цель: существо в своем могильнике.
        /// </summary>
        public static readonly GraveyardTarget Own = new GraveyardTarget(new Languages.Phrase("target.graveyard.own"), true, false);
        /// <summary>
        /// Цель: сушество во вражеском могильнике.
        /// </summary>
        public static readonly GraveyardTarget Enemy = new GraveyardTarget(new Languages.Phrase("target.graveyard.enemy"), false, true);
        /// <summary>
        /// Цель: существо в любом могильнике.
        /// </summary>
        public static readonly GraveyardTarget Both = new GraveyardTarget(new Languages.Phrase("target.graveyard.both"), true, true);
        /// <summary>
        /// Цель: жертвуемое существо в своем могильнике.
        /// </summary>
        public static readonly GraveyardTarget Sacrifice = new GraveyardTarget(new Languages.Phrase("target.graveyard.own.sacrifice"), true, false);
        /// <summary>
        /// Цель: воскрешаемое существо в своем могильнике.
        /// </summary>
        public static readonly GraveyardTarget OwnResurrect = new GraveyardTarget(new Languages.Phrase("target.graveyard.own.resurrect"), true, false, CanResurrect);

        private bool _own, _enemy;
        private TargetPredicate<GraveyardItem> _condition;

        public GraveyardTarget(Languages.Phrase notice, bool own, bool enemy) : this(notice, own, enemy, null) {
        }
        public GraveyardTarget(Languages.Phrase notice, bool own, bool enemy, TargetPredicate<GraveyardItem> condition) : base(notice) {
            _own = own;
            _enemy = enemy;
            _condition = condition;
        }

        public override bool IsRealTarget {
            get { return true; }
        }

        protected override void AutoSelectTab(Player player) {
            player.DefaultTab = TabType.Graveyard;
            player.SelectPlayer(_enemy && !_own ? player.Enemy : player);
        }

        /// <summary>
        /// Число целей равно числу карт в могильниках.
        /// </summary>
        public override int GetCount(AbstractObject caster) {
            int count = 0;
            if (_own)
                count += caster.Owner.Graveyard.Count;
            if (_enemy)
                count += caster.Owner.Enemy.Graveyard.Count;
            return count;
        }

        /// <summary>
        /// Целевые регионы: карты в могильниках.
        /// </summary>
        public override bool AcceptRegion(Region region) {
            var pgr = region as PlayerGraveyardRegion;
            if (pgr == null)
                return false;
            if (!(pgr.Player == Request.Player ? _own : _enemy))
                return false;
            if (pgr.Item.Antimagic)
                return false;
            if (_condition != null && !_condition(Request, pgr.Item))
                return false;
            return true;
        }

        public override TargetArgs GetArgs(Region region) {
            var pgr = region as PlayerGraveyardRegion;
            return pgr != null ? new GraveyardTargetArgs(Request.Player, Request.Caster, new GraveyardData(pgr.Player, pgr.Item)) : null;
        }

        /// <summary>
        /// Условие на существо в могильнике: может быть воскрешено.
        /// </summary>
        public static bool CanResurrect(TargetRequest request, GraveyardItem item) {
            return item.CanResurrect;
        }
    }

    [TypeId("graveyard")]
    public class GraveyardTargetArgs : TargetArgs<GraveyardData> {
        [Serialize, XmlName("target")]
        private GraveyardData _target;

        public GraveyardTargetArgs() {
        }
        public GraveyardTargetArgs(Player player, AbstractObject caster, GraveyardData target) : base(player, caster) {
            _target = target;
        }

        public override GraveyardData Target {
            get { return _target; }
        }
    }

    public struct GraveyardData {
        [XmlName("owner"), Reference(true, typeof(bool), Serialization.Resolvers.GamePlayer)]
        public Player Owner;
        [XmlName("item"), DefaultValue(-1)]
        public int ItemNumber;

        public GraveyardData(Player owner, GraveyardItem item) {
            Owner = owner;
            ItemNumber = Owner.Graveyard.IndexOf(item);
        }

        public GraveyardItem Item {
            get { return Owner.Graveyard.GetOrDefault(ItemNumber); }
        }

        public void MoveToSecondDeck() {
            Owner.Graveyard.MoveTo(Item, Owner.SecondDeck);
        }
    }
}
